/**
 * 判断此对象是否是Object类型
 * @param obj
 */
function isObject(obj: any): boolean {
  return Object.prototype.toString.call(obj) === '[object Object]';
}

/**
 * 判断此类型是否是Array类型
 * @param arr
 */
function isArray(arr: any): boolean {
  return Object.prototype.toString.call(arr) === '[object Array]';
}

/**
 * 深度比较两个对象是否相等
 * @param objOne
 * @param objTwo
 * @returns {boolean}
 */
function compare(objOne: any, objTwo: any): boolean {
  // 类型为基本类型时,如果相同,则返回true
  if (objOne === objTwo) return true;
  if (isObject(objOne) && isObject(objTwo) && Object.keys(objOne).length === Object.keys(objTwo).length) {
    // 类型为对象并且元素个数相同
    // 遍历所有对象中所有属性,判断元素是否相同
    const allKeys = Object.keys(objOne);
    for (let i = 0, { length } = allKeys; i < length; i += 1) {
      const key = allKeys[i];
      if (!compare(objOne[key], objTwo[key])) {
        // 对象中具有不相同属性 返回false
        return false;
      }
    }
  } else if (isArray(objOne) && isArray(objTwo) && objOne.length === objTwo.length) {
    // 类型为数组并且数组长度相同
    for (let i = 0, { length } = objOne; i < length; i += 1) {
      if (!compare(objOne[i], objTwo[i])) {
        // 如果数组元素中具有不相同元素,返回false
        return false;
      }
    }
  } else {
    return objOne === objTwo;
  }
  // 走到这里,说明数组或者对象中所有元素都相同,返回true
  return true;
}

/**
 * 比较两个字典内元素是否相等
 * @param objOne
 * @param objTwo
 * @returns {boolean}
 */
function equals(objOne: any, objTwo: any): boolean {
  return compare(objOne, objTwo);
}

export { isObject, isArray, compare, equals };
export default { isObject, isArray, compare, equals };
